/*
 * Copyright (C) 拾光分享网 
 * All rights reserved, Designed By www.hiai.top.
 * Email：goodsking@163.com.
 */
package top.hiai.login;

import com.jfinal.kit.HashKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.ehcache.CacheKit;
import top.hiai.common.model.Session;
import top.hiai.common.model.User;

import java.io.IOException;
import java.util.Date;
import java.util.Random;

/**
* @Author www.hiai.top
* @Email  goodsking@163.com
* @Message 更多资源尽在www.hiai.top
* @Introduction 类的介绍
*/

public class LoginService {
	private User userDao = new User().dao();
	public static final LoginService me = new LoginService();
	// 存放登录用户的 cacheName
	public static final String loginAccountCacheName = "loginAccount";
	// "jfinalId" 仅用于 cookie 名称，其它地方如 cache 中全部用的 "sessionId" 来做 key
	public static final String sessionIdName = "jfinalId";
	
	public static final String basePath = "/upload/avatar";
	
	/**
	 * 登录成功返回 sessionId 与 loginAccount，否则返回一个 msg
	 */
	public Ret login(String email, String password,boolean keepLogin,String loginIp) {
		email = email.toLowerCase().trim();//邮箱全部小写
		password = password.trim();
		User loginAccount = userDao.findFirst("select * from bbs_user where email=? limit 1", email);
		
		if (loginAccount == null) {
			return Ret.fail().set("msg", "用户名或密码不正确");
		}
		if (loginAccount.isStatusLockId()) {
			return Ret.fail().set("msg", "账号已被锁定");
		}

		String salt = loginAccount.getSalt();
		String hashedPass = HashKit.sha256(salt + password);
		// 未通过密码验证
		if (loginAccount.getPassword().equals(hashedPass) == false) {
			return Ret.fail().set("msg", "用户名或密码不正确");
		}
		System.out.println("是否："+keepLogin);
		// 如果用户勾选保持登录，暂定过期时间为 3 年，否则为 120 分钟，单位为秒
		long liveSeconds =  keepLogin ? 3 * 365 * 24 * 60 * 60 : 120 * 60;
		// 传递给控制层的 cookie
		int maxAgeInSeconds = (int)(keepLogin ? liveSeconds : -1);
		// expireAt 用于设置 session 的过期时间点，需要转换成毫秒
		long expireAt = System.currentTimeMillis() + (liveSeconds * 1000);
		// 保存登录 session 到数据库
		Session session = new Session();
		String sessionId = StrKit.getRandomUUID();
		session.setSid(sessionId);
		session.setAccountId(loginAccount.getUid());
		session.setExpireAt(expireAt);
		if ( ! session.save()) {
			return Ret.fail().set("msg", "保存 session 到数据库失败，请联系管理员");
		}

		loginAccount.removeSensitiveInfo();                                 // 移除 password 与 salt 属性值
		loginAccount.put("sessionId", sessionId);                          // 保存一份 sessionId 到 loginAccount 备用
		CacheKit.put(loginAccountCacheName, sessionId, loginAccount);

		createLoginLog(loginAccount.getUid(), loginIp);

		return Ret.ok(sessionIdName, sessionId)
						.set(loginAccountCacheName, loginAccount)
						.set("maxAgeInSeconds", maxAgeInSeconds);   // 用于设置 cookie 的最大存活时间	
	}
	/**
	 * 用户注册
	 * @throws IOException 
	 */
	public Ret register(String nickName,String email,String password) throws IOException{
		nickName = nickName.trim();
		email = email.toLowerCase().trim();		//邮箱全部小写
		password = password.trim();
		
		if (nickName.contains("@") || nickName.contains("＠")) { // 全角半角都要判断
			return Ret.fail().set("msg", "昵称不能包含 \"@\" 字符");
		}
		
		if (nickName.contains(" ") || nickName.contains("　")) { // 检测是否包含半角或全角空格
			return Ret.fail().set("msg", "昵称不能包含空格");
		}

		User loginAccount = userDao.findFirst("select * from bbs_user where email=? limit 1", email);
		if (loginAccount != null) {
			return Ret.fail().set("msg", "邮箱已被注册，如果忘记密码，可以使用密码找回功能。");
		}
		
		// 密码加盐 hash
		String salt = HashKit.generateSaltForSha256();
		password = HashKit.sha256(salt + password);
		
		User user = new User();
		user.setNickName(nickName);
		user.setEmail(email);
		user.setPassword(password);
		user.setSalt(salt);
		user.setCreateAt(new Date());
		
//		//生成头像的路径
//		String absolutePath = PathKit.getWebRootPath() + "/upload/avatar/";
//		
//		//System.out.println("用户头像"+absolutePath);
//		
//		//生成随机的用户头像的用户名，随机的6位数字
//		String outName = genSixRandomNum();
//		
//		//AvatarUtil.generateImg(nickName, outName);
//		/**
//		 * nickName			用户输入的头像
//		 * absolutePath		存入的路劲
//		 * outName			输入的头像名称
//		 */
//		AvatarUtils.generateImg(nickName, absolutePath, outName);
		
		int random=(int)(Math.random()*10+1);
		
		//保存用户的头像
		user.setAvatar( random + ".png");
		
		if(user.save()){
			return Ret.ok("msg", "注册成功，请登录。");
		}else{
			return Ret.fail().set("msg", "注册失败，请告知管理员");
		}
	}
	
	/**
	 * 判断用户登录的SessionId
	 * @param sessionId
	 * @return
	 */
	public User getLoginAccountWithSessionId(String sessionId) {
		return CacheKit.get(loginAccountCacheName, sessionId);
	}
	/**
	 * 退出登录
	 */
	public void logout(String sessionId) {
		if (sessionId != null) {
			CacheKit.remove(loginAccountCacheName, sessionId);
			Session.dao.deleteById(sessionId);
		}
	}
	
	/**
	 * 通过 sessionId 获取登录用户信息
	 * sessoin表结构：session(id, accountId, expireAt)
	 *
	 * 1：先从缓存里面取，如果取到则返回该值，如果没取到则从数据库里面取
	 * 2：在数据库里面取，如果取到了，则检测是否已过期，如果过期则清除记录，
	 *     如果没过期则先放缓存一份，然后再返回
	 */
	public User loginWithSessionId(String sid, String loginIp) {
		Session session = Session.dao.findById(sid);
		if (session == null) {      // session 不存在
			return null;
		}
		if (session.isExpired()) {  // session 已过期
			session.delete();		// 被动式删除过期数据，此外还需要定时线程来主动清除过期数据
			return null;
		}
		User loginAccount = userDao.findById(session.getAccountId());
		// 找到 loginAccount 并且 是正常状态 才允许登录
		if (loginAccount != null && loginAccount.isStatusOk()) {
			loginAccount.removeSensitiveInfo();                                 // 移除 password 与 salt 属性值
			loginAccount.put("sessionId", sid);                          // 保存一份 sessionId 到 loginAccount 备用
			CacheKit.put(loginAccountCacheName, sid, loginAccount);
			createLoginLog(loginAccount.getUid(), loginIp);
			return loginAccount;
		}
		return null;
	}
	
	/**
	 * 创建用户登录日志
	 * @param accountId
	 * @param loginIp
	 */
	private void createLoginLog(Integer accountId, String loginIp) {
		Record loginLog = new Record().set("accountId", accountId).set("loginIp", loginIp).set("addtime", new Date());
		Db.save("bbs_login_log", loginLog);
	}
	
	/**
	 * 生成六位随机数
	 * @return
	 */
	public static String genSixRandomNum(){
		Random random = new Random();
		String result="";
		for (int i=0;i<6;i++)
		{
			result+=random.nextInt(10);
		}
		return result;
	}

}